package com.hsc.mvc.tag;

import com.hsc.mvc.util.StringUtil;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;

/**
 * @author
 * @date 2025-05-18
 * @Description
 */
public class MappingTag {

    // 将下面的xml映射关系映射成java对象
    //    <mapper name="/test1.do" class="com.controller.TestController" method="t1">
    //        <!--方法的参数名称age、参数类型int-->
    //        <param-type name="age" type="cookie">int</param-type>
    //        <param-type name="sex" type="header">java.lang.String</param-type>
    //    </mapper>

    // 方法名
    private String nameStr;
    // 类的全类名
    private String classStr;
    private String methodStr;
    // Xml 文件中的配置 param-type
    List<ParamTypeTag> paramTypeTagList;

    // 我们将类的反射在这里的Class 对象也进行保存
    private Class<?> mappingClass;
    // 以及方法也进行保存
    // 请求对应的映射的方法 方法名称和方法参数 methodName methodParams
    private Method method;


    public String getNameStr() {
        return nameStr;
    }

    public void setNameStr(String nameStr) {
        this.nameStr = nameStr;
    }

    public String getClassStr() {
        return classStr;
    }

    /**
     * 设置类名 同时设置类对象
     *
     * @param classStr
     */
    public void setClassStr(String classStr) {
        this.classStr = classStr;
        try {
            // 根据类名得到类对象 然后进行设置
            Class<?> aClass = Class.forName(classStr);
            setMappingClass(aClass);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public String getMethodStr() {
        return methodStr;
    }

    public void setMethodStr(String methodStr) {
        this.methodStr = methodStr;
        // 反射得到的类对象不能为空 并且方法的参数对象不能空
        if (this.mappingClass != null && paramTypeTagList != null) {
            setMethod();
        }

    }

    /**
     * 对内私有 外部不可操作
     * <param-type name="age" type="cookie">int</param-type>
     * <param-type name="sex" type="header">java.lang.String</param-type>
     */
    private void setMethod() {
        // 根据xml文件中的设置的方法参数类型 得到对应的参数类型对象
        // 获取 int 类型 java.lang.String 两个参数类型
        try {
            Class[] paramTypesClasses = new Class[paramTypeTagList.size()];
            for (int i = 0; i < paramTypeTagList.size(); i++) {
                ParamTypeTag paramTypeTag = paramTypeTagList.get(i);
                // 得到里面的text  java.lang.String 字符串
                String text = paramTypeTag.getText();
                // 进行字符转换为对象 java.lang.String --》 Class
                Class parameClass = null;
                parameClass = paramTypeStr2Class(text);
                paramTypesClasses[i] = parameClass;
            }
            // 得到参数类型 反射得到方法对象
            this.method = mappingClass.getMethod(methodStr, paramTypesClasses);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // 存储
    }

    /**
     * 将字符串转换为对应的类型
     *
     * @param text
     * @return
     */
    private Class paramTypeStr2Class(String text) throws ClassNotFoundException {
        switch (text) {
            case "int":
                return int.class;
            case "byte":
                return byte.class;
            case "short":
                return short.class;
            case "long":
                return Long.class;
            case "float":
                return Float.class;
            case "double":
                return double.class;
            case "boolean":
                return boolean.class;
            case "char":
                return char.class;
            default:
                return Class.forName(text);
        }

    }

    public List<ParamTypeTag> getParamTypeTagList() {
        return paramTypeTagList;
    }

    public void setParamTypeTagList(List<ParamTypeTag> paramTypeTagList) {
        this.paramTypeTagList = paramTypeTagList;
    }

    public Class<?> getMappingClass() {
        return mappingClass;
    }

    /**
     * 设置类对象的同时 也设置方法对象
     *
     * @param mappingClass
     */
    public void setMappingClass(Class<?> mappingClass) {
        this.mappingClass = mappingClass;
        if (!StringUtil.isEmpty(methodStr) && paramTypeTagList != null) {
            this.setMethod();
        }
    }

    /**
     * 对外的api，可以获得最终可以使用的Method对象
     *
     * @return
     */
    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

}
